Skip to main content

Posts tagged with 'asp.net mvc'

OnActionExecuted method in an action filter will be run after the controller action it is filtering is executed. The context object that gets passed in of type ActionExecutedContext, which is very similar to ActionExecutingContext in the types of information you can get with these exceptions:

  • There is no ActionParameters dictionary property.
  • You will get some information related to an unhandled exception:
    • Exception - the exception that was thrown by the action
    • ExceptionHandled - set this to true if you've handled the exception in OnActionExecuted (otherwise it will be bubbled up)
    • Canceled - this can get a bit confusing, but if the process was canceled by setting a different result in OnActionExecuting this will be set to 'true', or you can set this to 'true' yourself to cancel further processing. For more info, see this post on how MVC handles filters and this discussion on the Canceled property.

I did another "kitchen sink" view of an ActionExecutedContext object:

Paired with a slightly different View, which results in:

Kitchen sink of ActionExceutedContext

Note that one of the most interesting things you can do is to change the result of the action (like I did to make the Kitchen Sink example possible). For instance, if you wanted to redirect to another action, show a different view, etc,

Thanks to Scott Hanselman, John Sonmez, and Pluralsight, you can get a free week of Pluralsight video training.

But Pluralsight has so much content; where to begin?

  • Since this is an AOP blog, obviously I'm going to recommend Donald Belcham's Aspect Oriented Programming in .NET. (Donald Belcham is a fellow Postsharp MVP).
  • Speaking of fellow Postsharp MVP's, Dustin Davis's T4 Templates course is another good choice. T4 is a powerful tool, and even though code generation is sometimes blamed for some coding atrocities, there is a right way and wrong way to do it, and lots of great use-cases that can make your application easier to maintain.
  • I've watched a few MVC Pluralsight courses from Scott Allen. And since I've been talking about MVC ActionFilters, I think it would also be worthwhile to watch ASP.NET MVC 3.0 Fundamentals.

Anything else you'd recommend at Pluralsight?

HELLO! This is one of the most popular posts on my blog, so I thought I would drop in a quick message to say "thank you!" for being a reader! If you're into podcasts, check out The Cross Cutting Concerns Podcast, with interviews about interesting and fun technology.

Building on the overview of ActionFilters in MVC, I'm going to go into a deeper dive on the various overrides that you can use inside of an ActionFilter, starting with OnActionExecuting.

OnActionExecuting is run before the Action is executed. You can put whatever code you want in here, including something as simple as just writing some raw HTML out before the Action is executed. But the real power comes from the filterContext parameter (of type ActionExecutingContext) that gets passed in to your OnActionExecuting method. This object gives you a whole bunch of information about the current context of the action that you are filtering. You can use this information to control logic or, conversely, you can manipulate the context according to your logic.

I wrote a "kitchen sink" filter combined with a Razor view to give you an idea of what kind of context you can view and/or manipulate.

All this does is expose the filterContext object to the view, where I can display some of the information available.

Here's a screenshot of the output. Note the URL (/Home/Index/parameter_value_here?anotherParam=99) as you look through the screenshot.

ActionExecutingContext view output

I've broken this output into 4 sections of different context information you can get. The first 4 are ASP.NET MVC specific: Controller, Action, Action Result, and Route. The last one, Http Context, is more general to ASP.NET.

Controller

You can get the controller name, the controller type, and even the controller instance, depending on your need. You can try to cast the controller to a specific controller if you want and access properties of that controller (I wouldn't recommend that generally, but you'll note that's how I did my kitchen sink action filter, by casting to the HomeController type).

Once you have a controller instance, you can access ViewBag, ViewData, TempData, all of which allows you to communicate to the action (and ultimately the view) if you choose to.

You can also access custom attributes here, which opens up some possibilities in declarative programming and use of metadata.

Action

You can again, get the name (of the action this time) if you want just that. You can also get some reflection information about the parameters. If you look at ActionParameters, you can get the parameter names along with the arguments. And once again, you can access custom attributes here, just as you can with controllers.

Action Result

You have the ability to get the ActionResult that the Action will return. At this point in the life cycle, that ActionResult is probably null, so I'm not exactly sure what you would want to do with it. But it's there. You could create a RedirectResult and immediately execute it; I suppose that might come in handy.

Route

I generally would not recommend messing around with routes in your action filters, as things could get really confusing in ASP.NET MVC, but you have access to RouteData, Values and DataTokens here too.

Http Context

Finally, Http Context, which contains just about everything you need to work with your standard Http objects like Response, Request, Session, etc. Do note that the objects you get are generally base classes (e.g. HttpResponseBase and HttpRequestBase), so you may not have access to some of the methods and properties that you are used to.

With the Http Context available, you can do some interesting things like checking to see if the session expired, and then either reloading the session from a db or cookie or something, or redirecting to a 'timeout' or other message page.

There's more?

This isn't even an exhaustive list of the stuff you can get to via the ActionExecutingContext being passed in. I've just tried to list some of the more useful properties and examples of data that could be in those properties and left out the esoteric stuff. But there's a lot of power here to do almost anything you want before an action starts executing.

You're going to see very similar properties in the other action filter override context objects, but there are some differences that I'll explore in later posts.

AOP may sound like this big high-falutin' term that's way too complicated, but guess what: you may already be using AOP and you don't even know it.

Do you using ASP.NET MVC? Ever used an ActionFilter? Congratulations, you have used aspect-oriented programming. If you are using MVC and haven't used an ActionFilter yet, read on, because you may want to start!

Writing an ActionFilter is very similar to writing a PostSharp aspect: you create a new class that inherits from a base class (ActionFilterAttribute), and then you override one or more methods depending on what you want the ActionFilter to do.  You apply the aspect to a method or entire class with an attribute. Unlike PostSharp, this form of AOP does not involve a post-compile step. The filtering takes place at runtime, and is invoked by the MVC framework. This means that if you are writing a unit test against the controller action, that test will not trigger the ActionFilter.

I'm going to be blogging some more details about what you can do with each of these, but when you are creating a class that inherits from ActionFilterAttribute, there are 4 methods that you can override 1 or more of:

  • OnActionExecuting - runs before the affected action
  • OnActionExecuted - runs after the affected action
  • OnResultExecuting - runs before the result of the action runs
  • OnResultExecuted - runs after the result of the action runs

If you use the [Authorize] attribute in MVC, then you are using an ActionFilter that's been pre-written for you (technically AuthorizeAttribute inherits from FilterAttribute, but it's the same principle). Instead of checking the User.Identity inside every one of your Controller actions, you can just slap the [Authorize] attribute on it and it will keep that cross-cutting concern encapsulated away from the rest of your Controller logic.

Matthew D. Groves

About the Author

Matthew D. Groves lives in Central Ohio. He works remotely, loves to code, and is a Microsoft MVP.

Latest Comments

Twitter